#include "room.h"
#include "messageProcessor.h"
#include <string.h>
#include <stdlib.h>
void roomInit(void){
	strcpy(lobby.name,"Lobby");
	lobby.list=NULL;
	lobby.next=NULL;
	lobby.roomID=0;
	roomList=NULL;
}
struct person* joinNewPerson(int fd, const char *name){
	if(fd<=0) return NULL;
	if(name==NULL) return NULL;
	struct person* newPerson=
		(struct person*)malloc(sizeof(struct person));
	if(newPerson==NULL) return NULL;
	newPerson->fd=fd;
	strncpy(newPerson->name,name,PERSON_NAME_MAX);
	newPerson->curRoom=NULL;
	if(enterRoomPerson(&lobby, newPerson)<0){
		free(newPerson);
		return NULL;
	}
	return newPerson;
}
//if not error : return number of people in room
//error        : return -1
int enterRoomPerson(struct room *room, struct person *person){
	int cnt=1;
	if(room==NULL || person==NULL) return -1;
	if(room->list==NULL){
		room->list=
			(struct personList*)malloc(sizeof(struct personList));
		if(room->list==NULL){
			return -1;
		}
		room->list->person=person;
		room->list->next=NULL;
	}
	else{
		struct personList *t=room->list;
		while(t->next!=NULL){
			cnt++;
		   	t=t->next;
		}
		t->next=
			(struct personList*)malloc(sizeof(struct personList));
	   	if(t->next==NULL)
			return -1;
		t->next->person=person;
		t->next->next=NULL;
		cnt++;
	}
	//만약 방이동한 사람이 그전 방의 방장이라면 처리하는 단계 필요
	//기존 사용자가 있던 룸 리스트에서 사용자를 제거.
	if(person->curRoom!=NULL){
		struct personList *t=person->curRoom->list;
		if(t->person==person){
			if(person->curRoom==&lobby){
				lobby.list=lobby.list->next;
			}
			else{
				person->curRoom->list=person->curRoom->list->next;
				deleteRoom(person->curRoom);
			}
			free(t);
		}
		else{
		   	while(t->next->person!=person) t=t->next;
			struct personList *t2;
			t2=t->next;
			t->next=t2->next;
			free(t2);
		}
	}
	person->curRoom=room;
	return cnt;
}
struct room *makeNewRoom(struct person *person, const char *name){
	static unsigned int roomIDcnt=1;
	if(name==NULL || strlen(name)==0 || person==NULL)
		return NULL;
	struct room *newRoom=
		(struct room*)malloc(sizeof(struct room));
	if(newRoom==NULL) return NULL;
	newRoom->list=NULL;
	newRoom->next=NULL;
	strncpy(newRoom->name,name,ROOM_NAME_MAX);
	if(enterRoomPerson(newRoom, person)<0){
		free(newRoom);
		return NULL;
	}
	if(roomList==NULL)
		roomList=newRoom;
	else{
		struct room *t=roomList;
		while(t->next!=NULL) t=t->next;
		t->next=newRoom;
	}

	newRoom->roomID=roomIDcnt;
	roomIDcnt++;
	return newRoom;
}
void deleteRoom(struct room *room){
	struct room *t=roomList;
	if(room==roomList){
		roomList=room->next;
	}
	else{
		while(t->next!=room) t=t->next;
		t->next=room->next;
	}
	//사람을 로비로 쫓아냄.
	if(room->list!=NULL){
		struct personList *personList=room->list;
		struct personList *lobbyList=lobby.list;
		if(lobbyList==NULL){
			lobby.list=personList;
		}
		else{
			while(lobbyList->next!=NULL) lobbyList=lobbyList->next;
			lobbyList->next=personList;
		}
		struct personList *tpl=personList;
		while(tpl!=NULL){
			tpl->person->curRoom=&lobby;
			//로비로 나간 사람들에게 메세지 주는 단계	
			unsigned char msg[3];
			msg[2]=0x10;
			writeMessage(msg,4,tpl->person->fd);
			tpl=tpl->next;
		}
	}
	free(room);
}
//사용자가 접속을 종료
void exitPerson(struct person *person){
	struct room *curRoom=person->curRoom;
	struct personList *personRoomList=curRoom->list;
	//접속을 끊은사람이 그방의 방장이라면
	if(personRoomList->person==person){		
		if(curRoom==&lobby){//로비라면 그냥 통상적으로 나간걸로 처리
			lobby.list=lobby.list->next;
		}
		else{//로비가 아니면 방 폭파
			curRoom->list=curRoom->list->next;
			deleteRoom(curRoom);
		}
		free(personRoomList);
	}
	else{
	   	while(personRoomList->next->person!=person) 
			personRoomList=personRoomList->next;
		struct personList *t=personRoomList;
		personRoomList=personRoomList->next;
		t->next=personRoomList->next;
		free(personRoomList);
	}
	free(person);		
}
struct room *findRoom(unsigned int roomID){
	if(roomID==0) return &lobby;
	struct room *t=roomList;
	while(t!=NULL){
		if(t->roomID==roomID) return t;	
		t=t->next;
	}
	return NULL;
}
struct person *findPerson(int fd){
	struct personList *pl=lobby.list;
	while(pl!=NULL){
		if(pl->person->fd==fd) return pl->person;
		pl=pl->next;
	}
	struct room *t=roomList;
	while(t!=NULL){
		pl=t->list;
		while(pl!=NULL){
			if(pl->person->fd==fd) return pl->person;
			pl=pl->next;
		}
		t=t->next;
	}
	return NULL;
}
